#include "StdAfx.h"
#include "PlayFab<%- api.name %>Api.h"
#include "PlayFabSettings.h"
<% if (hasClientOptions) { %>
#include "PlayFabDataGatherer.h" // #THIRD_KIND_PLAYFAB_DATA_GATHERER: gwatson (2017/09/12) - Added PlayFab data gatherer to send system information events to PlayFab on login
<% } %>
using namespace PlayFab<%- gemName %>Sdk;
<% if (hasClientOptions) { %>
// Client-Specific
AZStd::string PlayFabClientApi::mUserSessionTicket;

bool PlayFabClientApi::IsClientLoggedIn()
{
    return mUserSessionTicket.length() != 0;
}

// #THIRD_KIND_PLAYFAB_SHUTDOWN_FIXES: - Added a logout function so that the statics can be destroyed before the system allocator.
void PlayFabClientApi::ForgetAllCredentials()
{
    // #THIRD_KIND_PLAYFAB_CRASH_WHEN_PC_IS_OFFLINE: szaluga (2017/08/05)
    // We're taking advantage of the SSO optimization implemented by AZStd::string (and virtually all popular compilers) -
    // small strings are using an internal buffer instead of the allocator.
    // Note: This was not possible with Aws::String, as it deliberately disabled SSO to fix some Android/gcc issuses,
    // but now that PlayFab uses AZStd::string, it should be safe to rely on this behaviour.
    mUserSessionTicket.set_capacity(0);
}

struct DeviceInfoRequest : public PlayFabBaseModel
{
    PlayFab::PlayFabDataGatherer::DataMap Info;

    DeviceInfoRequest() : Info() {}
    DeviceInfoRequest(const DeviceInfoRequest& src) : Info(src.Info) {}

    DeviceInfoRequest(const rapidjson::Value& obj) : DeviceInfoRequest() { readFromValue(obj); }

    ~DeviceInfoRequest() {}

    void writeJSON(PFStringJsonWriter& writer) const override
    {
        writer.StartObject();
        if (!Info.empty()) {
            writer.String("Info");
            writer.StartObject();
            for (auto iter = Info.begin(); iter != Info.end(); ++iter) {
                writer.String(iter->first.c_str());
                iter->second.writeJSON(writer);
            }
            writer.EndObject();
        }
        writer.EndObject();
    }

    bool readFromValue(const rapidjson::Value& obj) override
    {
        const Value::ConstMemberIterator Info_member = obj.FindMember("Info");
        if (Info_member != obj.MemberEnd()) {
            for (Value::ConstMemberIterator iter = Info_member->value.MemberBegin(); iter != Info_member->value.MemberEnd(); ++iter) {
                Info[iter->name.GetString()] = iter->value.GetUint();
            }
        }
        return true;
    }
};

void PlayFabClientApi::MultiStepClientLogin(bool needsAttribution)
{
    // #THIRD_KIND_PLAYFAB_DATA_GATHERER: gwatson (2017/09/12) - Added PlayFab data gatherer to send system information events to PlayFab on login
    // Output the system information event
    PlayFab::PlayFabDataGatherer dataGatherer;
    DeviceInfoRequest request;
    dataGatherer.GatherData(request.Info);
    // AZ_TracePrintf("PlayFab", dataGatherer.GenerateReport(request.Info).c_str());

    PlayFabRequest* newRequest = new PlayFabRequest(PlayFabSettings::playFabSettings->getURL("/Client/ReportDeviceInfo"), Aws::Http::HttpMethod::HTTP_POST, "X-Authorization", mUserSessionTicket, request.toJSONString(), nullptr, nullptr, nullptr, nullptr);
    PlayFabRequestManager::playFabHttp->AddRequest(newRequest);
    // #THIRD_KIND_PLAYFAB_DATA_GATHERER: gwatson (2017/09/12) - Added PlayFab data gatherer to send system information events to PlayFab on login

    if (needsAttribution && !PlayFabSettings::playFabSettings->disableAdvertising && PlayFabSettings::playFabSettings->advertisingIdType.length() > 0 && PlayFabSettings::playFabSettings->advertisingIdValue.length() > 0)
    {
        ClientModels::AttributeInstallRequest request;
        if (PlayFabSettings::playFabSettings->advertisingIdType == PlayFabSettings::playFabSettings->AD_TYPE_IDFA)
            request.Idfa = PlayFabSettings::playFabSettings->advertisingIdValue;
        else if (PlayFabSettings::playFabSettings->advertisingIdType == PlayFabSettings::playFabSettings->AD_TYPE_ANDROID_ID)
            request.Adid = PlayFabSettings::playFabSettings->advertisingIdValue;
        else
            return;
        AttributeInstall(request, nullptr, nullptr);
    }
}
<% } %>
// PlayFab<%- api.name %> Api
PlayFab<%- api.name %>Api::PlayFab<%- api.name %>Api() {}
<% for(var i in api.calls) { var apiCall = api.calls[i]; %>
void PlayFab<%- api.name %>Api::<%- apiCall.name %>(
<% if(HasRequest(apiCall, api)) { %>    <%- api.name %>Models::<%- apiCall.request %>& request,<% } %>
    ProcessApiCallback<<%- api.name %>Models::<%- apiCall.result %>> callback,
    ErrorCallback errorCallback,
    void* customData
)
{
<%- GetRequestActions(apiCall, api) %>
<% if(HasRequest(apiCall, api)) {
%>    PlayFabRequest* newRequest = new PlayFabRequest(PlayFabSettings::playFabSettings->getURL("<%- apiCall.url %>"), Aws::Http::HttpMethod::HTTP_<%- apiCall.method %>, <%- GetAuthParams(apiCall) %>, request.toJSONString(), customData, callback, errorCallback, On<%- apiCall.name %>Result);
<% } else {
%>    PlayFabRequest* newRequest = new PlayFabRequest(PlayFabSettings::playFabSettings->getURL("<%- apiCall.url %>"), Aws::Http::HttpMethod::HTTP_<%- apiCall.method %>, <%- GetAuthParams(apiCall) %>, "", customData, callback, errorCallback, On<%- apiCall.name %>Result);
<% } %>    PlayFabRequestManager::playFabHttp->AddRequest(newRequest);
}

void PlayFab<%- api.name %>Api::On<%- apiCall.name %>Result(PlayFabRequest* request)
{
    if (PlayFabBaseModel::DecodeRequest(request))
    {
        <%- api.name %>Models::<%- apiCall.result %>* outResult = new <%- api.name %>Models::<%- apiCall.result %>;
        outResult->readFromValue(request->mResponseJson->FindMember("data")->value);

<%- GetResultActions(apiCall, api) %>
        if (request->mResultCallback != nullptr)
        {
            ProcessApiCallback<<%- api.name %>Models::<%- apiCall.result %>> successCallback = reinterpret_cast<ProcessApiCallback<<%- api.name %>Models::<%- apiCall.result %>>>(request->mResultCallback);
            successCallback(*outResult, request->mCustomData);
        }
        delete outResult;
        delete request;
    }
}
<% } %>
